package com.ty.user.starter.shiro;

import com.ty.user.starter.entity.User;
import com.ty.user.starter.entity.vo.MenuVo;
import com.ty.user.starter.entity.vo.RoleVo;
import com.ty.user.starter.service.MenuService;
import com.ty.user.starter.service.UserService;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;

import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;

public class UserMgtRealm extends AuthorizingRealm {
    @Autowired
    private UserService userService;
    @Autowired
    private MenuService menuService;


    @Override
    public boolean supports(AuthenticationToken token) {
        return token instanceof UsernamePasswordToken;
    }


    /**
     * 用户授权
     *
     * @param principalCollection 主体集合
     * @return 单个主题的存储授权数据（角色、权限等)
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        Collection principals = principalCollection.fromRealm(getName());
        if (principals.isEmpty()) {
            return null;
        }
        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
        Long userId = (Long) principals.toArray()[0];

        /* 添加角色信息 */
        List<RoleVo> roles = userService.getRoles(userId);
        if (!CollectionUtils.isEmpty(roles)) {
            simpleAuthorizationInfo.addRoles(roles.parallelStream().map(RoleVo::getBusCode).collect(Collectors.toList()));
        }

        /* 添加权限信息 */
        List<MenuVo> menus = menuService.getPermissions(userService.getById(userId));
        if (!CollectionUtils.isEmpty(menus)) {
            List<String> perms = menus.parallelStream().map(MenuVo::getPerm).distinct().collect(Collectors.toList());
            simpleAuthorizationInfo.addStringPermissions(perms);
        }
        return simpleAuthorizationInfo;
    }

    /**
     * 用户认证
     *
     * @param authenticationToken 账户主体和身份的综合凭证
     * @return 认证信息
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        String principal = (String) authenticationToken.getPrincipal();
        User user = userService.getByUsername(principal);
        return new SimpleAuthenticationInfo(user, user.getPwd(), ByteSource.Util.bytes(user.getSalt()), getName());
    }
}
